﻿using System;
using RayDen.Library.Core.Primitives;

namespace RayDen.Library.Components.Surface
{
    [Serializable]
    public class MatteMirrorMaterial : SurfaceBsdf
    {
        public override BrdfType Type
        {
            get { return BrdfType.Glossy; }
        }
        public
            MatteMirrorMaterial(RgbSpectrum col, RgbSpectrum refl, bool reflSpecularBounce)
        {
            matte = new MatteMaterial(col);
            mirror = new MirrorMaterial(refl, reflSpecularBounce);
            matteFilter = matte.GetKd().Filter();
            mirrorFilter = mirror.GetKr().Filter();
            totFilter = matteFilter + mirrorFilter;

            mattePdf = matteFilter / totFilter;
            mirrorPdf = mirrorFilter / totFilter;
        }

        public override bool IsDiffuse() { return true; }
        public override bool IsSpecular() { return true; }


        public override void f(ref Vector wo, ref Vector wi, ref Normal N, ref RgbSpectrum in_fs, out RgbSpectrum fs)
        {
            matte.f(ref wo, ref wi, ref N, ref in_fs, out fs);
            fs *= mattePdf;
        }

        public override float Pdf(ref Vector wo, ref Vector wi, BxDFTypes bxDFType)
        {
            return mattePdf * mirrorPdf;
        }

        public override void Sample_f(ref Vector wo, ref Normal N, ref Normal shadeN, ref RgbSpectrum in_f, float u0, float u1, float u2, ref SurfaceTextureData surfaceData, out BsdfSampleData result)
        {
            float comp = u2 * totFilter;

            if (comp > matteFilter)
            {
                mirror.Sample_f(ref wo, ref N, ref shadeN, ref in_f, u0, u1, u2, ref surfaceData, out result);
                result.Pdf *= mirrorPdf;
            }
            else
            {
                matte.Sample_f(ref wo, ref N, ref shadeN, ref in_f, u0, u1, u2, ref surfaceData, out result);
                result.Pdf *= mattePdf;
            }
        }

        //public override void Sample_f(ref Vector wo, out Vector wi, ref Normal N, ref Normal shadeN, float u0, float u1, float u2, ref RgbSpectrum col, out BsdfSampleData result1)
        //{
        //    RgbSpectrum temp = matte.GetKd();
        //    matte = new MatteMaterial(col);
        //    matteFilter = matte.GetKd().Filter();
        //    mirrorFilter = mirror.GetKr().Filter();
        //    totFilter = matteFilter + mirrorFilter;

        //    mattePdf = matteFilter / totFilter;
        //    mirrorPdf = mirrorFilter / totFilter;

        //    this.Sample_f(ref wo, ref N, ref shadeN, u0, u1, u2, ref hitInfo.TextureData, out result1);

        //    matte = new MatteMaterial(temp);
        //    matteFilter = matte.GetKd().Filter();
        //    mirrorFilter = mirror.GetKr().Filter();
        //    totFilter = matteFilter + mirrorFilter;

        //    mattePdf = matteFilter / totFilter;
        //    mirrorPdf = mirrorFilter / totFilter;
        //    wi = result1.Wi;
        //}


        public MatteMaterial matte;
        public MirrorMaterial mirror;
        public float matteFilter, mirrorFilter, totFilter, mattePdf, mirrorPdf;
    };
}